package edu.ynu.se.xiecheng.achitectureclass.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

@Service
@PropertySource("classpath:application.properties")
public class SensorTokenService {

    private final PropertyService propertyService;
    public SensorTokenService(PropertyService propertyService) {
        this.propertyService= propertyService;
    }

    @Value("${fbox.client_id}")
    private String clientId;

    @Value("${fbox.client_secret}")
    private String clientSecret;

    @Value("${fbox.token_url}")
    private String tokenUrl;

    @Value("${fbox.access_token}")
    private String accessToken;

    @Value("${fbox.getTokenTime}")
    private String getTokenTime;

    private static final String TOKEN_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @EventListener(ApplicationReadyEvent.class)
    @Order(1)
    public String getAccessToken() {
        if (accessToken != null && !accessToken.isEmpty() && !isTokenExpired()) {
            return accessToken;
        }

        // 获取新的 token
        String newToken = fetchNewToken();
        saveTokenToConfig(newToken);
        return newToken;
    }

    private String fetchNewToken() {
        String url = tokenUrl;
        RestTemplate restTemplate = new RestTemplate();

        // 设置请求参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("scope", "fbox");
        params.add("client_id", clientId);
        params.add("client_secret", clientSecret);
        params.add("grant_type", "client_credentials");

        // 创建请求体
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);

        // 发送POST请求
        ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url, HttpMethod.POST, entity, new ParameterizedTypeReference<>() {});


        // 解析token
        if (response.getStatusCode() == HttpStatus.OK) {
            Map<String, Object> responseBody = response.getBody();
            return (String) Objects.requireNonNull(responseBody).get("access_token");
        } else {
            throw new RuntimeException("Failed to fetch access token.");
        }
    }

    private boolean isTokenExpired() {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(TOKEN_TIME_FORMAT);
                Date tokenDate = sdf.parse(getTokenTime);
                long diff = new Date().getTime() - tokenDate.getTime();
                return diff > 7200 * 1000; // 2 hours in milliseconds
            } catch (Exception e) {
                return true;
            }
    }
    private void saveTokenToConfig(String newToken) {
        // 保存token及获取时间到配置文件
        Map<String, String> properties = propertyService.getProperties();
        // 更新token和获取时间
        String currentTime = new SimpleDateFormat(TOKEN_TIME_FORMAT).format(new Date());
        properties.put("fbox.access_token", newToken);
        properties.put("fbox.getTokenTime", currentTime);
        // 写回配置文件
        propertyService.writeProperties(properties);
        // 更新字段
        this.accessToken = newToken;
        this.getTokenTime = new SimpleDateFormat(TOKEN_TIME_FORMAT).format(new Date());
    }
}

